#include<iostream>
#include<boost/asio.hpp>
#include<memory>
#include<thread>


using namespace boost;

void session(boost::asio::ip::tcp::socket &sock)
{
    const unsigned char BUFF_SIZE = 30;
    char buffer_receive[BUFF_SIZE];
    int receive_length =  sock.receive(asio::buffer(buffer_receive, BUFF_SIZE));
    if (receive_length <= 0){
        std::cout << "receive failed" << std::endl;
    }
    else
    {
        std::string rec_buf(buffer_receive,BUFF_SIZE);
        std::cout << "receive buffer = " << rec_buf << std::endl;

        int send_length = sock.send(asio::buffer(rec_buf.c_str(), rec_buf.length()));
        if (send_length <= 0) {
            std::cout << "send failed" << std::endl;
            return;
        }
        else
        {
            std::cout << "send success!" << std::endl;
        }
    }
}


int accept_new_connection(){
    // The size of the queue containing the pending connection
            // requests.
    const int BACKLOG_SIZE = 30;
    // Step 1. Here we assume that the server application has
    // already obtained the protocol port number.
    unsigned short port_num = 3333;
    // Step 2. Creating a server endpoint.
    asio::ip::tcp::endpoint ep(asio::ip::address_v4::any(),
        port_num);
    asio::io_context  ios;
    try {
        // Step 3. Instantiating and opening an acceptor socket.
        asio::ip::tcp::acceptor acceptor(ios, ep.protocol());
        // Step 4. Binding the acceptor socket to the 
        // server endpint.
        acceptor.bind(ep);
        // Step 5. Starting to listen for incoming connection
        // requests.
        std::cout << "step5."<< "\n";
        std::cout << "listening."<< "\n";
        acceptor.listen(BACKLOG_SIZE);
       
        // Step 6. Creating an active socket.
        asio::ip::tcp::socket sock(ios);
        // Step 7. Processing the next connection request and 
        // connecting the active socket to the client.
        acceptor.accept(sock);
         std::cout << "accept a connect."<< "\n";
        // At this point 'sock' socket is connected to 
        //the client application and can be used to send data to
        // or receive data from it.
        session(sock);

    }
    catch (system::system_error& e) {
        std::cout << "Error occured! Error code = " << e.code()
            << ". Message: " << e.what();
        return e.code().value();
    }

    return 0;
}



int main(int argc, char const *argv[])
{
    
    accept_new_connection();
    return 0;
}
